﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver;
using Sustainalytics.Entities;
using Sustainalytics.Entities.ProductInvolvement;
using Sustainalytics.ClientDW.Entities;
using Sustainalytics.ClientDW.Entities.Universes;
using Sustainalytics.DataLayer;
using Sustainalytics.Utils.Configuration;
using Sustainalytics.BusinessResearchProductStates.Entities.ResearchState;
using Sustainalytics.ESG.Entities;

namespace Sustainalytics.ReportGenerator.BL
{
    public class TearSheetReportDataProvider
    {
        private readonly CancellationToken _token;
        private readonly int _bulkSize;
        private int _skip;
        private readonly IReadOnlyDictionary<string, string> _connectionStrings;
        private readonly string[] _accountNames;
        private IDictionary<string, int[]> _sustainabilityAssessmentDictionary;
        private IDictionary<string, int[][]> _thematicAssessmentDictionary;
        private IDictionary<string, int[]> _controversyAssessmentDictionary;
        private IDictionary<Guid, int> _highestControversyLevelDictionary;
        private List<ProductInvolvementFramework> _piPIIndicator;
        private IEnumerable<Guid> _companyIds;
        public int CompanyCount => _companyIds.Count();

        public TearSheetReportDataProvider(int bulkSize, CancellationToken token, IReadOnlyDictionary<string, string> connectionStrings, string[] accountNames)
        {
            _bulkSize = bulkSize;
            _token = token;
            _connectionStrings = connectionStrings;
            _accountNames = accountNames;
            _skip = 0;
        }


        public void OneTimeDataRead()
        {
            var companyIds = GetAccountCompanyIds();

            _companyIds = companyIds;
            _sustainabilityAssessmentDictionary = new Dictionary<string, int[]>();
            _thematicAssessmentDictionary = new ConcurrentDictionary<string, int[][]>();
            _controversyAssessmentDictionary = new ConcurrentDictionary<string, int[]>();
            var maxDegreeOfParallelism = SettingsHelper.Read("MaxDegreeOfParallelism", 1);

            var options = new ParallelOptions
            {
                CancellationToken = _token,
                MaxDegreeOfParallelism = maxDegreeOfParallelism
            };

            var actions = new List<Action>
            {
                () => { ReadProductInvolvementIndicators(); },
                () => { PrepareSustainability(companyIds); },
                () => { PrepareControversies(companyIds); }
            };

            var exceptions = new ConcurrentQueue<Exception>();

            Parallel.ForEach(actions, options, action =>
            {
                try
                {
                    action();
                }
                catch (Exception ex)
                {
                    exceptions.Enqueue(ex);
                }
            });

            if (exceptions.Count > 0)
            {
                throw new AggregateException(exceptions);
            }

        }

        public TearSheetReportDataSource[] GetCompanyReportData(Guid companyId)
        {
            return GetNextData(companyId);
        }

        private TearSheetReportDataSource[] GetNextData(Guid id)
        {
            var batch = new ConcurrentBag<TearSheetReportDataSource>();


            var companyIds = id == Guid.Empty
                ? _companyIds.Skip(_skip).Take(_bulkSize).ToList()
                : _companyIds.Where(x => x == id).ToList();

            _skip += _bulkSize;


            if (!companyIds.Any()) return batch.ToArray();


            var maxDegreeOfParallelism = SettingsHelper.Read("MaxDegreeOfParallelism", 1);

            var options = new ParallelOptions()
            {
                CancellationToken = _token,
                MaxDegreeOfParallelism = maxDegreeOfParallelism
            };


            IDictionary<Guid, CorporateData> corporateDataDictionary = null;
            IDictionary<Guid, RPCompanyProfile> rpCompanyProfileDictionary = null;
            IDictionary<Guid, Entities.RiskRatings.RiskRatingResearchProfile> riskRatingResearchProfileDictionary = null;
            IDictionary<Guid, OverallPerformance> overallPerformanceDictionary = null;
            IDictionary<Guid, List<EventIndicator>> eventIndicatorsDictionary = new Dictionary<Guid, List<EventIndicator>>();
            IDictionary<Guid, List<KeyEsgIssue>> keyEsgIssuesDictionary = new Dictionary<Guid, List<KeyEsgIssue>>();
            IDictionary<Guid, ProductInvolvementData> piCompanyAssessmentDictionary = null;

            var actions = new List<Action>
            {
                () => { corporateDataDictionary = GetCorporateData(companyIds); },
                () => { rpCompanyProfileDictionary = GetRpCompanyProfiles(companyIds); },
                () => { riskRatingResearchProfileDictionary = GetRiskRatingResearchProfiles(companyIds); },
                () => { overallPerformanceDictionary = GetOverallPerformances(companyIds); },
                () => { keyEsgIssuesDictionary = GetKeyEsgIssues(companyIds); },
                () => { eventIndicatorsDictionary = GetEventIndicators(companyIds); },
                () => { _piPIIndicator = ReadProductInvolvementIndicators(); },
                () => { piCompanyAssessmentDictionary = GetProductInvolvementCompanyAssessment(companyIds); }
            };


            var exceptions = new ConcurrentQueue<Exception>();

            Parallel.ForEach(actions, options, action =>
            {
                try
                {
                    action();
                }
                catch (Exception ex)
                {
                    exceptions.Enqueue(ex);
                }
            });

            if (exceptions.Count > 0)
            {
                throw new AggregateException(exceptions);
            }


            exceptions = new ConcurrentQueue<Exception>();

            Parallel.ForEach(companyIds, options, companyId =>
            {
                try
                {
                    var corporateData = corporateDataDictionary.ContainsKey(companyId)
                        ? corporateDataDictionary[companyId]
                        : null;


                    var reportDataSource = new TearSheetReportDataSource
                    {
                        CompanyId = companyId,

                        CorporateData = corporateData,


                        SustainabilityAssessments =
                            corporateData != null &&
                            _sustainabilityAssessmentDictionary.ContainsKey(corporateData.PeerGroup)
                                ? _sustainabilityAssessmentDictionary[corporateData.PeerGroup]
                                : new[] { 0, 0, 0, 0, 0 },
                        ThematicAssessments = corporateData != null &&
                            _thematicAssessmentDictionary.ContainsKey(corporateData.PeerGroup)
                                ? _thematicAssessmentDictionary[corporateData.PeerGroup]
                                : new[] { new[] { 0, 0, 0, 0, 0 }, new[] { 0, 0, 0, 0, 0 }, new[] { 0, 0, 0, 0, 0 } },

                        ControversyAssessments =
                            corporateData != null &&
                            _controversyAssessmentDictionary.ContainsKey(corporateData.PeerGroup)
                                ? _controversyAssessmentDictionary[corporateData.PeerGroup]
                                : new[] { 0, 0, 0, 0, 0, 0 },

                        RPCompanyProfile = rpCompanyProfileDictionary.ContainsKey(companyId)
                            ? rpCompanyProfileDictionary[companyId]
                            : null,

                        RiskRatingResearchProfile = riskRatingResearchProfileDictionary.ContainsKey(companyId)
                            ? riskRatingResearchProfileDictionary[companyId]
                            : null,

                        OverallPerformance = overallPerformanceDictionary.ContainsKey(companyId)
                            ? overallPerformanceDictionary[companyId]
                            : null,

                        HighestControversyLevel = _highestControversyLevelDictionary.ContainsKey(companyId)
                            ? _highestControversyLevelDictionary[companyId]
                            : 0,


                        KeyEsgIssues = keyEsgIssuesDictionary.ContainsKey(companyId)
                            ? keyEsgIssuesDictionary[companyId]
                            : new List<KeyEsgIssue>(),

                        EventIndicators = eventIndicatorsDictionary.ContainsKey(companyId)
                            ? eventIndicatorsDictionary[companyId]
                            : new List<EventIndicator>(),


                        ProductInvolvementIndicators = _piPIIndicator,

                        ProductInvolvementCompanyAssessment = piCompanyAssessmentDictionary.ContainsKey(companyId)
                            ? piCompanyAssessmentDictionary[companyId]
                            : null
                    };


                    batch.Add(reportDataSource);
                }
                catch (Exception ex)
                {
                    exceptions.Enqueue(ex);
                }
            });

            if (exceptions.Count > 0)
            {
                throw new AggregateException(exceptions);
            }

            return batch.ToArray();
        }

        private List<Guid> GetAccountCompanyIds()
        {
            var companyIds = MongoDatabaseFactory
                    .GetDatabase(_connectionStrings["ClientDW"])
                    .GetCollection<CorporateData>(typeof(CorporateData).Name)
                    .Find(cd => cd.ComprehensiveEsgResearchState.ResearchState == ResearchState.ResearchAvailable)
                    .Project(cd => cd.Id)
                    .ToList();

            if (_accountNames.Length == 0)
            {
                return new List<Guid>
                {
                    new Guid("6c6845ff-4d9e-4f4d-b920-962af834ef0a"), // Chevron Corporation
                    new Guid("98c4e8cc-0383-4295-b71d-f838a32d5f27"), // Wal-Mart Stores Inc.
               };
            }

            var accountId = MongoDatabaseFactory
                .GetDatabase(_connectionStrings["ClientPlatform"])
                .GetCollection<Account>(typeof(Account).Name)
                .Find(a => a.Name == _accountNames[0])
                .Project(a => a.Id)
                .SingleOrDefault();

            var universeId = MongoDatabaseFactory
                .GetDatabase(_connectionStrings["ClientUniverses"])
                .GetCollection<Universe>(typeof(Universe).Name)
                .Find(u => u.AccountId == accountId && u.Name == "ESG Research")
                .Project(u => u.Id)
                .SingleOrDefault();


            var ids = MongoDatabaseFactory
                .GetDatabase(_connectionStrings["ClientUniverses"])
                .GetCollection<UniverseCompany>(typeof(UniverseCompany).Name)
                .Find(uc => uc.AccountId == accountId && uc.UniverseId == universeId)
                .Project(uc => uc.CompanyId)
                .ToList();


            return ids.Intersect(companyIds).ToList();
        }


        private IDictionary<Guid, CorporateData> GetCorporateData(IEnumerable<Guid> companyIds)
        {
            var corporateData = MongoDatabaseFactory
                .GetDatabase(_connectionStrings["ClientDW"])
                .GetCollection<CorporateData>(typeof(CorporateData).Name)
                .Find(x => companyIds.Contains(x.Id))
                .ToEnumerable()
                .ToDictionary(kv => kv.Id);

            return corporateData;
        }

        private IDictionary<Guid, RPCompanyProfile> GetRpCompanyProfiles(IEnumerable<Guid> companyIds)
        {
            return MongoDatabaseFactory
                .GetDatabase(_connectionStrings["ClientDW"])
                .GetCollection<RPCompanyProfile>(typeof(RPCompanyProfile).Name)
                .Find(x => companyIds.Contains(x.Id))
                .ToEnumerable()
                .ToDictionary(kv => kv.Id);
        }

        private IDictionary<Guid, Entities.RiskRatings.RiskRatingResearchProfile> GetRiskRatingResearchProfiles(IEnumerable<Guid> companyIds)
        {
            return MongoDatabaseFactory
                .GetDatabase(_connectionStrings["RiskRatingsResearchDW"])
                .GetCollection<Entities.RiskRatings.RiskRatingResearchProfile>(typeof(Entities.RiskRatings.RiskRatingResearchProfile).Name)
                .Find(x => companyIds.Contains(x.Id))
                .Project(x => new Entities.RiskRatings.RiskRatingResearchProfile
                {
                    Id = x.Id,
                    EsgRiskManagementComment = x.EsgRiskManagementComment,

                    MaterialEsgIssues = x.MaterialEsgIssues
                    .Where(mei => mei.IsMain)
                    .Select(mei => new Entities.RiskRatings.RiskRatingMaterialEsgIssueBase
                    {
                        ExternalId = mei.ExternalId,
                        Name = mei.Name,
                        ManagementComment = mei.ManagementComment
                    })
                })
                .ToList()
                .ToDictionary(kv => kv.Id);
        }

        private IDictionary<Guid, OverallPerformance> GetOverallPerformances(IEnumerable<Guid> companyIds)
        {
            var rpPerformanceData = MongoDatabaseFactory
                .GetDatabase(_connectionStrings["ClientDW"])
                .GetCollection<RPCompanyESGComputationResult>(typeof(RPCompanyESGComputationResult).Name)
                .Find(x => companyIds.Contains(x.Id))
                .Project(x => new
                {
                    x.Id,
                    x.OverallPerformance,
                    x.EnvironmentPerformance,
                    x.SocialPerformance,
                    x.GovernancePerformance,
                    x.IsInReferenceUniverse,
                    x.PreparednessScore,
                    x.DisclosureScore,
                    x.QuantitativePerformanceScore,
                    x.QualitativePerformanceScore
                })
                .ToList();

            var overallPerformanceDictionary = rpPerformanceData.ToDictionary(x => x.Id, x => new OverallPerformance
            {
                CompanyScore = (int)Math.Round(x.OverallPerformance.Score, MidpointRounding.AwayFromZero),
                CompanyAssessment = new RPAssessment()
                {
                    Id = x.OverallPerformance.Assessment.Id,
                    Name = x.OverallPerformance.Assessment.Name
                },
                CompanyRank = x.OverallPerformance.Rank.Value ?? 0,
                CompanyCount = x.OverallPerformance.GroupCount,
                Percentile = x.OverallPerformance.Percentile,

                EnvironmentScore = (int)Math.Round(x.EnvironmentPerformance.Score, MidpointRounding.AwayFromZero),
                EnvironmentAssessment = new RPAssessment()
                {
                    Id = x.EnvironmentPerformance.Assessment.Id,
                    Name = x.EnvironmentPerformance.Assessment.Name
                },
                SocialScore = (int)Math.Round(x.SocialPerformance.Score, MidpointRounding.AwayFromZero),
                SocialAssessment = new RPAssessment()
                {
                    Id = x.SocialPerformance.Assessment.Id,
                    Name = x.SocialPerformance.Assessment.Name
                },
                GovernanceScore = (int)Math.Round(x.GovernancePerformance.Score, MidpointRounding.AwayFromZero),
                GovernanceAssessment = new RPAssessment()
                {
                    Id = x.GovernancePerformance.Assessment.Id,
                    Name = x.GovernancePerformance.Assessment.Name
                },
                IsInReferenceUniverse = x.IsInReferenceUniverse,
                CategoriesPerformance = new List<CategoryPerformance>()
                        {
                            new CategoryPerformance
                            {
                                CategoryName = "Preparedness",
                                CompanyScore = (int)Math.Round(x.PreparednessScore.Score, MidpointRounding.AwayFromZero),
                            },
                            new CategoryPerformance
                            {
                                CategoryName = "Disclosure",
                                CompanyScore = (int)Math.Round(x.DisclosureScore.Score, MidpointRounding.AwayFromZero),
                            },
                            new CategoryPerformance
                            {
                                CategoryName = "Quantitative Performance",
                                CompanyScore = (int)Math.Round(x.QuantitativePerformanceScore.Score, MidpointRounding.AwayFromZero),
                            },
                            new CategoryPerformance
                            {
                                CategoryName = "Qualitative Performance - Controversies",
                                CompanyScore = (int)Math.Round(x.QualitativePerformanceScore.Score, MidpointRounding.AwayFromZero),
                            }
                        }
            });

            return overallPerformanceDictionary;
        }


         private List<string> GetPeerGroups(IEnumerable<Guid> companyIds)
        {
            var peerGroups = MongoDatabaseFactory
                .GetDatabase(_connectionStrings["ClientDW"])
                .GetCollection<CorporateData>(typeof(CorporateData).Name)
                .Find(x => companyIds.Contains(x.Id))
                .Project(cd => cd.PeerGroup)
                .ToEnumerable()
                .GroupBy(x => x).Select(x => x.Key).ToList();

            return peerGroups;
        }

        private IDictionary<string, List<Guid>> GetPeerGroupCompanyIds(List<string> peerGroups, bool isControversyResearch = false)
        {
            var builder = Builders<CorporateData>.Filter;
            var filter = builder.In(cd => cd.PeerGroup, peerGroups);
            filter = isControversyResearch
                ? filter & builder.Eq(cd => cd.ControversyResearchState.ResearchState, ResearchState.ResearchAvailable)
                : filter & builder.Eq(cd => cd.ComprehensiveEsgResearchState.ResearchState, ResearchState.ResearchAvailable);

            var dictionary = MongoDatabaseFactory
                .GetDatabase(_connectionStrings["ClientDW"])
                .GetCollection<CorporateData>(typeof(CorporateData).Name)
                .Find(filter)
                .Project(cd => new
                {
                    cd.Id,
                    cd.PeerGroup
                })
                .ToEnumerable()
                .GroupBy(s => s.PeerGroup)
                .ToDictionary(k => k.Key, v => v.Select(cd => cd.Id).ToList());

            return dictionary;
        }

        private void PrepareSustainability(IEnumerable<Guid> companyIds)
        {
            var peerGroups = GetPeerGroups(companyIds);
            var peerGroupDictionary = GetPeerGroupCompanyIds(peerGroups);

            foreach (var peerGroup in peerGroups)
            {
                var ids = peerGroupDictionary.ContainsKey(peerGroup)
                    ? peerGroupDictionary[peerGroup]
                    : new List<Guid>();

                if (!ids.Any()) continue;


                var overallPerformance = MongoDatabaseFactory
                    .GetDatabase(_connectionStrings["ClientDW"])
                    .GetCollection<RPCompanyESGComputationResult>(typeof(RPCompanyESGComputationResult).Name)
                    .Find(x => ids.Contains(x.Id))
                    .ToList();

                var peersAssesments = overallPerformance.GroupBy(x => x.OverallPerformance.Assessment.Id)
                    .Select(x => new { AssessmentId = x.Key, CompanyCount = x.Count() })
                    .ToDictionary(k => k.AssessmentId, v => v.CompanyCount);

                var environmentPeersAssesments = overallPerformance.GroupBy(x => x.EnvironmentPerformance.Assessment.Id)
                    .Select(x => new { AssessmentId = x.Key, CompanyCount = x.Count() })
                    .ToDictionary(k => k.AssessmentId, v => v.CompanyCount);
                var socialPeersAssesments = overallPerformance.GroupBy(x => x.SocialPerformance.Assessment.Id)
                    .Select(x => new { AssessmentId = x.Key, CompanyCount = x.Count() })
                    .ToDictionary(k => k.AssessmentId, v => v.CompanyCount);
                var governancePeersAssesments = overallPerformance.GroupBy(x => x.GovernancePerformance.Assessment.Id)
                   .Select(x => new { AssessmentId = x.Key, CompanyCount = x.Count() })
                   .ToDictionary(k => k.AssessmentId, v => v.CompanyCount);

                var count = overallPerformance.Count;

                var percentages = new List<int>();
                var environmentPercentages = new List<int>();
                var socialPercentages = new List<int>();
                var governancePercentages = new List<int>();

                for (var id = 1; id <= 5; id++)
                {
                    var percent = peersAssesments.ContainsKey(id)
                        ? Convert.ToInt32((decimal)peersAssesments[id] / count * 100)
                        : 0;
                    percentages.Add(percent);

                    percent = environmentPeersAssesments.ContainsKey(id)
                        ? Convert.ToInt32((decimal)environmentPeersAssesments[id] / count * 100)
                        : 0;
                    environmentPercentages.Add(percent);

                    percent = socialPeersAssesments.ContainsKey(id)
                        ? Convert.ToInt32((decimal)socialPeersAssesments[id] / count * 100)
                        : 0;
                    socialPercentages.Add(percent);

                    percent = governancePeersAssesments.ContainsKey(id)
                        ? Convert.ToInt32((decimal)governancePeersAssesments[id] / count * 100)
                        : 0;
                    governancePercentages.Add(percent);
                }

                _sustainabilityAssessmentDictionary.Add(peerGroup, percentages.ToArray());

                _thematicAssessmentDictionary.Add(peerGroup, new[]
                {
                    environmentPercentages.ToArray(),
                    socialPercentages.ToArray(),
                    governancePercentages.ToArray()
                });
            }

        }


        private void PrepareControversies(List<Guid> companyIds)
        {
            _highestControversyLevelDictionary = new ConcurrentDictionary<Guid, int>();

            var controversies = MongoDatabaseFactory
                .GetDatabase(_connectionStrings["ClientDW"])
                .GetCollection<EventIndicator>(typeof(EventIndicator).Name)
                .Aggregate()
                .Group(new BsonDocument
                {
                    {"_id", "$CompanyId"},
                    {"HighestControversyLevel", new BsonDocument {{"$max", "$AnswerCategory"}}}
                })
                .ToList()
                .ToDictionary(k => new Guid(k.GetElement(0).Value.AsByteArray), v => v.GetElement(1).Value.AsInt32);


            foreach (var companyId in companyIds)
            {
                var answerCategory = controversies.ContainsKey(companyId)
                        ? controversies[companyId]
                        : 0;

                _highestControversyLevelDictionary.Add(companyId, answerCategory);
            }

            var peerGroups = GetPeerGroups(companyIds);
            var peerGroupDictionary = GetPeerGroupCompanyIds(peerGroups, true);

            foreach (var peerGroup in peerGroups)
            {
                var ids = peerGroupDictionary.ContainsKey(peerGroup)
                    ? peerGroupDictionary[peerGroup]
                    : new List<Guid>();

                if (!ids.Any()) continue;

                var groupControversies = controversies
                    .Where(x => ids.Contains(x.Key))
                    .Select(x => new { CompanyId = x.Key, HighestControversyLevel = x.Value })
                    .ToList();

                if (!groupControversies.Any()) continue;

                var peerGroupAssesments = groupControversies.GroupBy(ei => ei.HighestControversyLevel)
                    .Select(g => new { HighestControversyLevel = g.Key, CompanyCount = g.Count() })
                    .ToDictionary(k => k.HighestControversyLevel, v => v.CompanyCount);

                var count = groupControversies.Count;

                var assesments = new List<int>();
                for (var id = 0; id <= 5; id++)
                {
                    var percent = peerGroupAssesments.ContainsKey(id)
                        ? Convert.ToInt32((decimal)peerGroupAssesments[id] / count * 100)
                        : 0;
                    assesments.Add(percent);
                }

                _controversyAssessmentDictionary.Add(peerGroup, assesments.ToArray());
            }
        }

        private List<ProductInvolvementFramework> ReadProductInvolvementIndicators()
        {
            var piIndicators = MongoDatabaseFactory
                .GetDatabase(_connectionStrings["ProductInvolvementDW"])
                .GetCollection<ProductInvolvementFramework>(typeof(ProductInvolvementFramework).Name)
                .Find(new BsonDocument())
                .ToEnumerable()
                .OrderBy(pi => pi.Symbol)
                .ToList();

            _piPIIndicator = piIndicators;

            return _piPIIndicator;
        }


        private IDictionary<Guid, List<KeyEsgIssue>> GetKeyEsgIssues(IEnumerable<Guid> companyIds)
        {
            var companyKeyEsgIssues = MongoDatabaseFactory
                .GetDatabase(_connectionStrings["ClientDW"])
                .GetCollection<CompanyKeyESGIssue>(typeof(CompanyKeyESGIssue).Name)
                .Find(x => companyIds.Contains(x.Id))
                .ToEnumerable();

            var keyEsgIssuesDictionary = companyKeyEsgIssues.ToDictionary(kei => kei.Id, kei => kei.KeyESGIssues);

            return keyEsgIssuesDictionary;
        }

        private readonly Dictionary<string, int> themeSortKey = new Dictionary<string, int>()
        {
            { "E", 1 },
            { "S", 2 },
            { "G", 3 },
        };

        private IDictionary<Guid, List<EventIndicator>> GetEventIndicators(IEnumerable<Guid> companyIds)
        {
            var eventIndicators = MongoDatabaseFactory
                .GetDatabase(_connectionStrings["ClientDW"])
                .GetCollection<EventIndicator>(typeof(EventIndicator).Name)
                .Find(x => companyIds.Contains(x.CompanyId) && x.AnswerCategory >= 3)
               .ToList();

            eventIndicators.ForEach(ei =>
            {
                ei.ControversyIndicatorNumber = ei.ControversyIndicatorNumber.Substring(0, 1);
                ei.ControversyIndicatorSortKey = themeSortKey.ContainsKey(ei.ControversyIndicatorNumber) ? themeSortKey[ei.ControversyIndicatorNumber] : 0;
            });

            var eventIndicatorsDictionary = eventIndicators
                .GroupBy(ei => ei.CompanyId)
                .ToDictionary(g => g.Key, ei => ei.OrderBy(x => x.ControversyIndicatorSortKey)
                    .ThenByDescending(x => x.AnswerCategory)
                    .ThenBy(x => x.ControversyIndicatorName + " - " + x.Name).ToList());

            return eventIndicatorsDictionary;
        }

        private IDictionary<Guid, ProductInvolvementData> GetProductInvolvementCompanyAssessment(IEnumerable<Guid> companyIds)
        {
            var piCompanyAssessmentCollection = MongoDatabaseFactory
                .GetDatabase(_connectionStrings["ClientDW"])
                .GetCollection<ProductInvolvementData>(typeof(ProductInvolvementData).Name)
                .Find(x => companyIds.Contains(x.Id))
                .ToEnumerable();

            var corporateDataCollection = MongoDatabaseFactory
                            .GetDatabase(_connectionStrings["ClientDW"])
                            .GetCollection<CorporateData>(typeof(CorporateData).Name)
                            .Find(cd => cd.ProductInvolvementResearchState.ResearchState == ResearchState.ResearchAvailable)
                            .Project(cd => cd.Id)
                            .ToList();

            var piCompanyAssessmentDictionary = piCompanyAssessmentCollection
                .Where(pi => corporateDataCollection.Contains(pi.Id))
                .ToDictionary(pi => pi.Id, pi => pi);

            return piCompanyAssessmentDictionary;
        }

    }
}
